// ESP32开发辅助工具主应用逻辑

// 应用状态管理
const appState = {
    chipModel: 'ESP32-WROOM-32',
    projectName: 'esp32_project',
    wifiEnabled: false,
    bluetoothEnabled: false,
    httpServerEnabled: false,
    otaEnabled: false,
    pinConfigurations: {},
    generatedCode: '',
    projectFiles: {},
    serialPort: null,
    serialReader: null,
    serialWriter: null,
    currentPin: null, // 当前正在配置的引脚
    debounceTimer: null, // 防抖定时器
    currentFileView: 'main.c' // 当前查看的文件
};

// DOM元素引用
const elements = {
    chipSelector: document.getElementById('chip-selector'),
    projectName: document.getElementById('project-name'),
    wifiEnable: document.getElementById('wifi-enable'),
    bluetoothEnable: document.getElementById('bluetooth-enable'),
    httpServerEnable: document.getElementById('http-server-enable'),
    otaEnable: document.getElementById('ota-enable'),
    pinConfiguration: document.getElementById('pin-configuration'),
    generateCodeBtn: document.getElementById('generate-code'),
    downloadZipBtn: document.getElementById('download-zip'),
    exportTextBtn: document.getElementById('export-text'),
    codePreview: document.getElementById('code-preview'),
    fileStructure: document.getElementById('file-structure'),
    connectDeviceBtn: document.getElementById('connect-device'),
    connectionStatus: document.getElementById('connection-status'),
    selectFirmwareBtn: document.getElementById('select-firmware'),
    firmwareFileInput: document.getElementById('firmware-file'),
    flashFirmwareBtn: document.getElementById('flash-firmware'),
    flashProgress: document.getElementById('flash-progress'),
    progressPercent: document.getElementById('progress-percent'),
    pinMode: document.getElementById('pin-mode'),
    savePinConfigBtn: document.getElementById('save-pin-config'),
    pinConfigModal: document.getElementById('pin-config-modal'),
    currentPin: document.getElementById('current-pin'),
    serialMonitor: document.getElementById('serial-monitor'),
    serialCommand: document.getElementById('serial-command'),
    sendCommandBtn: document.getElementById('send-command'),
    tabButtons: document.querySelectorAll('.tab-btn')
};

// 初始化应用
function initApp() {
    // 绑定事件监听器
    bindEventListeners();
    
    // 加载保存的配置
    loadConfiguration();
    
    // 初始化引脚图
    updatePinDiagram();
    
    // 初始化标签页
    initTabs();
    
    console.log('ESP32开发辅助工具已初始化');
    logToMonitor('系统已启动', 'info');
}

// 绑定事件监听器
function bindEventListeners() {
    elements.chipSelector.addEventListener('change', handleChipChange);
    elements.projectName.addEventListener('input', handleProjectNameChange);
    elements.wifiEnable.addEventListener('change', handleFeatureToggle);
    elements.bluetoothEnable.addEventListener('change', handleFeatureToggle);
    elements.httpServerEnable.addEventListener('change', handleFeatureToggle);
    elements.otaEnable.addEventListener('change', handleFeatureToggle);
    elements.generateCodeBtn.addEventListener('click', generateCode);
    elements.downloadZipBtn.addEventListener('click', downloadProject);
    elements.exportTextBtn.addEventListener('click', exportProjectStructure);
    elements.connectDeviceBtn.addEventListener('click', connectToDevice);
    elements.selectFirmwareBtn.addEventListener('click', () => elements.firmwareFileInput.click());
    elements.flashFirmwareBtn.addEventListener('click', flashFirmware);
    elements.firmwareFileInput.addEventListener('change', handleFirmwareSelection);
    elements.savePinConfigBtn.addEventListener('click', savePinConfiguration);
    elements.sendCommandBtn.addEventListener('click', sendSerialCommand);
    elements.serialCommand.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') sendSerialCommand();
    });
    
    // 标签页事件
    elements.tabButtons.forEach(btn => {
        btn.addEventListener('click', () => switchTab(btn));
    });
}

// 初始化标签页
function initTabs() {
    elements.tabButtons.forEach(btn => {
        btn.classList.remove('active');
    });
    elements.tabButtons[0].classList.add('active');
}

// 切换标签页
function switchTab(btn) {
    // 更新激活状态
    elements.tabButtons.forEach(b => b.classList.remove('active'));
    btn.classList.add('active');
    
    // 获取文件名
    const fileName = btn.getAttribute('data-file');
    appState.currentFileView = fileName;
    
    // 更新代码预览
    updateCodePreview(appState.projectFiles[fileName] || `/* ${fileName} 文件内容 */`);
}

// 处理芯片型号变更
function handleChipChange(event) {
    appState.chipModel = event.target.value;
    saveConfiguration();
    updatePinDiagram();
    debounceGenerateCode();
    logToMonitor(`芯片型号已更改为: ${appState.chipModel}`, 'info');
}

// 处理项目名称变更
function handleProjectNameChange(event) {
    appState.projectName = event.target.value;
    saveConfiguration();
    debounceGenerateCode();
}

// 处理功能切换（WiFi/蓝牙等）
function handleFeatureToggle() {
    appState.wifiEnabled = elements.wifiEnable.checked;
    appState.bluetoothEnabled = elements.bluetoothEnable.checked;
    appState.httpServerEnabled = elements.httpServerEnable.checked;
    appState.otaEnabled = elements.otaEnable.checked;
    saveConfiguration();
    debounceGenerateCode();
    logToMonitor('功能配置已更新', 'info');
}

// 防抖处理代码生成
function debounceGenerateCode() {
    // 清除之前的定时器
    clearTimeout(appState.debounceTimer);
    
    // 设置新的定时器
    appState.debounceTimer = setTimeout(() => {
        generateCode();
    }, 500); // 500ms 防抖延迟
}

// 更新引脚图
function updatePinDiagram() {
    // 根据芯片型号加载不同的引脚图
    let pinDiagramHTML = '';
    
    if (appState.chipModel === 'ESP32-WROOM-32') {
        pinDiagramHTML = `
            <div class="text-center">
                <h3 class="text-lg font-semibold mb-4">ESP32-WROOM-32 引脚图</h3>
                <div class="grid grid-cols-4 gap-2 max-w-md mx-auto">
                    ${Array.from({length: 24}, (_, i) => {
                        const pinConfig = appState.pinConfigurations[i];
                        const configuredClass = pinConfig ? 'pin-configured border-purple-500' : 'border-gray-600';
                        return `
                            <div class="p-2 border rounded-lg cursor-pointer hover:bg-indigo-900 transition pin-item ${configuredClass}" 
                                 data-pin="${i}" onclick="openPinConfigModal(${i})">
                                <div class="font-medium">GPIO${i}</div>
                                <div class="text-xs text-gray-400">${pinConfig ? pinConfig.mode : '未配置'}</div>
                            </div>
                        `;
                    }).join('')}
                </div>
            </div>
        `;
    } else if (appState.chipModel === 'ESP32-C3-MINI-1') {
        pinDiagramHTML = `
            <div class="text-center">
                <h3 class="text-lg font-semibold mb-4">ESP32-C3-MINI-1 引脚图</h3>
                <div class="grid grid-cols-4 gap-2 max-w-md mx-auto">
                    ${Array.from({length: 18}, (_, i) => {
                        const pinConfig = appState.pinConfigurations[i];
                        const configuredClass = pinConfig ? 'pin-configured border-purple-500' : 'border-gray-600';
                        return `
                            <div class="p-2 border rounded-lg cursor-pointer hover:bg-indigo-900 transition pin-item ${configuredClass}" 
                                 data-pin="${i}" onclick="openPinConfigModal(${i})">
                                <div class="font-medium">GPIO${i}</div>
                                <div class="text-xs text-gray-400">${pinConfig ? pinConfig.mode : '未配置'}</div>
                            </div>
                        `;
                    }).join('')}
                </div>
            </div>
        `;
    } else if (appState.chipModel === 'ESP32-S3') {
        pinDiagramHTML = `
            <div class="text-center">
                <h3 class="text-lg font-semibold mb-4">ESP32-S3 引脚图</h3>
                <div class="grid grid-cols-4 gap-2 max-w-md mx-auto">
                    ${Array.from({length: 32}, (_, i) => {
                        const pinConfig = appState.pinConfigurations[i];
                        const configuredClass = pinConfig ? 'pin-configured border-purple-500' : 'border-gray-600';
                        return `
                            <div class="p-2 border rounded-lg cursor-pointer hover:bg-indigo-900 transition pin-item ${configuredClass}" 
                                 data-pin="${i}" onclick="openPinConfigModal(${i})">
                                <div class="font-medium">GPIO${i}</div>
                                <div class="text-xs text-gray-400">${pinConfig ? pinConfig.mode : '未配置'}</div>
                            </div>
                        `;
                    }).join('')}
                </div>
            </div>
        `;
    } else {
        pinDiagramHTML = `
            <div class="text-center">
                <h3 class="text-lg font-semibold mb-4">${appState.chipModel} 引脚图</h3>
                <div class="grid grid-cols-4 gap-2 max-w-md mx-auto">
                    ${Array.from({length: 12}, (_, i) => {
                        const pinConfig = appState.pinConfigurations[i];
                        const configuredClass = pinConfig ? 'pin-configured border-purple-500' : 'border-gray-600';
                        return `
                            <div class="p-2 border rounded-lg cursor-pointer hover:bg-indigo-900 transition pin-item ${configuredClass}" 
                                 data-pin="${i}" onclick="openPinConfigModal(${i})">
                                <div class="font-medium">GPIO${i}</div>
                                <div class="text-xs text-gray-400">${pinConfig ? pinConfig.mode : '未配置'}</div>
                            </div>
                        `;
                    }).join('')}
                </div>
            </div>
        `;
    }
    
    elements.pinConfiguration.innerHTML = pinDiagramHTML;
}

// 打开引脚配置模态框
function openPinConfigModal(pinNumber) {
    appState.currentPin = pinNumber;
    
    // 设置当前引脚显示
    elements.currentPin.textContent = `GPIO${pinNumber}`;
    
    // 设置当前引脚的配置值
    const pinConfig = appState.pinConfigurations[pinNumber];
    if (pinConfig) {
        elements.pinMode.value = pinConfig.mode;
    } else {
        elements.pinMode.value = 'output'; // 默认值
    }
    
    // 显示模态框
    elements.pinConfigModal.classList.remove('hidden');
}

// 关闭引脚配置模态框
function closePinConfigModal(event) {
    if (event && event.target !== elements.pinConfigModal) return;
    elements.pinConfigModal.classList.add('hidden');
    appState.currentPin = null;
}

// 保存引脚配置
function savePinConfiguration() {
    if (appState.currentPin === null) return;
    
    // 保存配置
    appState.pinConfigurations[appState.currentPin] = {
        mode: elements.pinMode.value
    };
    
    // 关闭模态框
    closePinConfigModal();
    
    // 更新引脚图
    updatePinDiagram();
    
    // 保存配置并重新生成代码
    saveConfiguration();
    debounceGenerateCode();
    
    logToMonitor(`引脚 GPIO${appState.currentPin} 已配置为 ${elements.pinMode.value} 模式`, 'success');
}

// 生成代码
function generateCode() {
    logToMonitor('开始生成代码...', 'info');
    
    // 生成主程序代码
    const mainCode = generateMainCode();
    
    // 生成CMakeLists.txt
    const cmakeCode = generateCMakeLists();
    
    // 生成sdkconfig
    const sdkConfig = generateSdkConfig();
    
    // 生成分区表（如果启用OTA）
    let partitionTable = null;
    if (appState.otaEnabled) {
        partitionTable = generatePartitionTable();
    }
    
    // 保存生成的代码到应用状态
    appState.generatedCode = mainCode;
    appState.projectFiles = {
        'main/main.c': mainCode,
        'CMakeLists.txt': cmakeCode,
        'sdkconfig': sdkConfig
    };
    
    // 如果启用了OTA，添加分区表
    if (partitionTable) {
        appState.projectFiles['partitions.csv'] = partitionTable;
    }
    
    // 更新代码预览
    updateCodePreview(mainCode);
    
    // 更新文件结构预览
    updateFileStructure();
    
    logToMonitor('代码生成完成', 'success');
}

// 生成主程序代码
function generateMainCode() {
    let code = `/* ESP32 项目主程序 - ${appState.projectName}
 * 芯片型号: ${appState.chipModel}
 * 生成时间: ${new Date().toLocaleString('zh-CN')}
 */

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
`;

    if (appState.wifiEnabled) {
        code += `#include "esp_wifi.h"
#include "esp_event.h"
#include "nvs_flash.h"
`;
    }

    if (appState.bluetoothEnabled) {
        code += `#include "esp_bt.h"
`;
    }

    if (appState.httpServerEnabled) {
        code += `#include "esp_http_server.h"
`;
    }

    if (appState.otaEnabled) {
        code += `#include "esp_ota_ops.h"
`;
    }

    // 添加引脚相关的头文件
    if (Object.keys(appState.pinConfigurations).length > 0) {
        code += `#include "driver/gpio.h"
`;
    }

    code += `
void app_main(void)
{
    printf("Hello from ${appState.projectName}!\\n");
    printf("芯片型号: ${appState.chipModel}\\n");
    
`;

    // 添加WiFi初始化代码
    if (appState.wifiEnabled) {
        code += `    // WiFi初始化代码
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    
    esp_netif_create_default_wifi_sta();
    
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    
    printf("WiFi功能已初始化\\n");
`;
    }

    // 添加蓝牙初始化代码
    if (appState.bluetoothEnabled) {
        code += `    // 蓝牙初始化代码
    esp_bluedroid_init();
    esp_bluedroid_enable();
    
    printf("蓝牙功能已初始化\\n");
`;
    }

    // 添加HTTP服务器初始化
    if (appState.httpServerEnabled) {
        code += `    // HTTP服务器初始化
    // TODO: 添加HTTP服务器配置代码
    
    printf("HTTP服务器功能已启用\\n");
`;
    }

    // 添加OTA初始化
    if (appState.otaEnabled) {
        code += `    // OTA功能初始化
    // TODO: 添加OTA配置代码
    
    printf("OTA更新功能已启用\\n");
`;
    }

    // 添加引脚配置代码
    Object.keys(appState.pinConfigurations).forEach(pin => {
        const config = appState.pinConfigurations[pin];
        code += `    // 配置GPIO${pin}为${config.mode}模式\n`;
        
        if (config.mode === 'output') {
            code += `    gpio_config_t io_conf_${pin};
    io_conf_${pin}.intr_type = GPIO_INTR_DISABLE;
    io_conf_${pin}.mode = GPIO_MODE_OUTPUT;
    io_conf_${pin}.pin_bit_mask = (1ULL << GPIO_NUM_${pin});
    io_conf_${pin}.pull_down_en = 0;
    io_conf_${pin}.pull_up_en = 0;
    gpio_config(&io_conf_${pin});
    
`;
        } else if (config.mode === 'input') {
            code += `    gpio_config_t io_conf_${pin};
    io_conf_${pin}.intr_type = GPIO_INTR_DISABLE;
    io_conf_${pin}.mode = GPIO_MODE_INPUT;
    io_conf_${pin}.pin_bit_mask = (1ULL << GPIO_NUM_${pin});
    io_conf_${pin}.pull_down_en = 0;
    io_conf_${pin}.pull_up_en = 1;
    gpio_config(&io_conf_${pin});
    
`;
        } else if (config.mode === 'pwm') {
            code += `    // TODO: 配置GPIO${pin}为PWM模式
    // 这里需要添加LEDC相关配置
    
`;
        } else if (config.mode === 'adc') {
            code += `    // TODO: 配置GPIO${pin}为ADC模式
    // 这里需要添加ADC相关配置
    
`;
        } else if (config.mode === 'uart') {
            code += `    // TODO: 配置GPIO${pin}为UART模式
    // 这里需要添加UART相关配置
    
`;
        } else if (config.mode === 'i2c') {
            code += `    // TODO: 配置GPIO${pin}为I2C模式
    // 这里需要添加I2C相关配置
    
`;
        } else if (config.mode === 'spi') {
            code += `    // TODO: 配置GPIO${pin}为SPI模式
    // 这里需要添加SPI相关配置
    
`;
        }
    });

    code += `    // 主循环
    while (1) {
        printf("运行中...\\n");
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}
`;

    return code;
}

// 生成CMakeLists.txt
function generateCMakeLists() {
    return `# 项目级CMakeLists.txt
# 项目名称: ${appState.projectName}
# 芯片型号: ${appState.chipModel}
# 生成时间: ${new Date().toLocaleString('zh-CN')}

cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(${appState.projectName})
`;
}

// 生成sdkconfig
function generateSdkConfig() {
    let config = `# SDK配置文件
# 项目名称: ${appState.projectName}
# 芯片型号: ${appState.chipModel}
# 生成时间: ${new Date().toLocaleString('zh-CN')}

CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
CONFIG_FREERTOS_HZ=100
`;

    if (appState.wifiEnabled) {
        config += `CONFIG_ESP_WIFI_ENABLED=y
CONFIG_LWIP_DHCP_MAX_NIP=3
`;
    }

    if (appState.bluetoothEnabled) {
        config += `CONFIG_BT_ENABLED=y
`;
    }

    if (appState.httpServerEnabled) {
        config += `CONFIG_HTTPD_SERVER_SUPPORT=y
`;
    }

    if (appState.otaEnabled) {
        config += `CONFIG_OTA_UPDATES_ENABLED=y
CONFIG_OTA_NUM_CUSTOM_PARTS=2
`;
    }

    // 添加引脚配置
    Object.keys(appState.pinConfigurations).forEach(pin => {
        const pinConfig = appState.pinConfigurations[pin];
        if (pinConfig.mode === 'adc') {
            config += `CONFIG_ADC_ENABLED=y
`;
        }
    });

    return config;
}

// 生成分区表
function generatePartitionTable() {
    if (!appState.otaEnabled) return null;
    
    return `# ESP-IDF Partition Table
# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x6000,
phy_init, data, phy,     0xf000,  0x1000,
factory,  app,  factory, 0x10000, 1M,
ota_0,    app,  ota_0,   ,        1M,
ota_1,    app,  ota_1,   ,        1M,
`;
}

// 更新代码预览
function updateCodePreview(code) {
    elements.codePreview.innerHTML = `<pre class="m-0 !bg-gray-900"><code class="language-c">${escapeHtml(code || '')}</code></pre>`;
    Prism.highlightAll();
}

// 更新文件结构预览
function updateFileStructure() {
    if (Object.keys(appState.projectFiles).length === 0) {
        elements.fileStructure.innerHTML = '<p class="text-gray-400 text-center">生成代码后将显示项目文件结构</p>';
        return;
    }

    let structureHtml = `
<div class="tree text-gray-300">
    <ul>
        <li>${appState.projectName}/
            <ul>
                <li><i class="fas fa-file-alt text-blue-400 mr-1"></i> CMakeLists.txt</li>
                <li><i class="fas fa-file-alt text-blue-400 mr-1"></i> sdkconfig</li>
`;

    if (appState.otaEnabled) {
        structureHtml += `                <li><i class="fas fa-file-alt text-blue-400 mr-1"></i> partitions.csv</li>
`;
    }

    structureHtml += `                <li class="mt-1">main/
                    <ul>
                        <li><i class="fas fa-file-code text-green-400 mr-1"></i> main.c</li>
                    </ul>
                </li>
`;

    // 如果有特殊组件，添加components目录
    if (hasSpecialComponents()) {
        structureHtml += `                <li class="mt-1">components/
                    <ul>
                        <li><i class="fas fa-folder text-yellow-400 mr-1"></i> ...</li>
                    </ul>
                </li>
`;
    }

    structureHtml += `            </ul>
        </li>
    </ul>
</div>`;

    elements.fileStructure.innerHTML = structureHtml;
}

// 检查是否有特殊组件
function hasSpecialComponents() {
    // 检查是否有需要特殊处理的引脚配置
    for (const pin in appState.pinConfigurations) {
        const config = appState.pinConfigurations[pin];
        if (['pwm', 'adc', 'uart', 'i2c', 'spi'].includes(config.mode)) {
            return true;
        }
    }
    return appState.httpServerEnabled || appState.otaEnabled;
}

// 下载项目
function downloadProject() {
    if (Object.keys(appState.projectFiles).length === 0) {
        alert('请先生成代码！');
        logToMonitor('下载失败：请先生成代码', 'error');
        return;
    }

    const zip = new JSZip();

    // 添加文件到zip
    Object.keys(appState.projectFiles).forEach(filename => {
        zip.file(filename, appState.projectFiles[filename]);
    });

    // 生成带时间戳的文件名，增加文件唯一性
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
    const fileName = `${appState.projectName}_${timestamp}.zip`;

    // 生成zip文件并下载
    zip.generateAsync({type:"blob"})
       .then(function(content) {
           saveAs(content, fileName);
           logToMonitor(`项目已准备下载，请检查浏览器下载栏`, 'success');
           showDownloadInstructions();
       });
       
    // 同时提供文本格式的项目内容作为备选方案
    exportProjectAsText();
}

// 导出项目为文本（备选方案）
function exportProjectAsText() {
    if (Object.keys(appState.projectFiles).length === 0) return;
    
    let projectText = `# ESP32 项目导出\n`;
    projectText += `项目名称: ${appState.projectName}\n`;
    projectText += `芯片型号: ${appState.chipModel}\n`;
    projectText += `生成时间: ${new Date().toLocaleString('zh-CN')}\n\n`;
    
    // 添加所有文件内容
    Object.keys(appState.projectFiles).forEach(filename => {
        projectText += `==================== ${filename} ====================\n`;
        projectText += appState.projectFiles[filename];
        projectText += `\n\n`;
    });
    
    // 保存到localStorage作为备份
    const backupKey = `esp32_project_backup_${new Date().getTime()}`;
    localStorage.setItem(backupKey, projectText);
    
    return projectText;
}

// 显示下载说明
function showDownloadInstructions() {
    // 检查是否已存在说明
    const existingInstructions = document.querySelector('.download-instructions');
    if (existingInstructions) {
        existingInstructions.remove();
    }
    
    // 创建说明元素
    const instructionDiv = document.createElement('div');
    instructionDiv.className = 'mt-4 p-4 bg-blue-900 rounded-lg text-sm download-instructions';
    instructionDiv.innerHTML = `
        <div class="flex items-start">
            <i class="fas fa-info-circle text-blue-400 mt-1 mr-2"></i>
            <div>
                <p class="font-semibold mb-2">下载说明：</p>
                <ul class="list-disc pl-5 space-y-1">
                    <li>如果浏览器提示安全风险，请点击"保留"或"允许下载"</li>
                    <li>Windows可能会标记ZIP文件，在下载完成后右键点击并选择"保留"</li>
                    <li>如果文件被系统删除，可以使用下方的"导出为文本"功能</li>
                    <li>解压后可在ESP-IDF环境中使用 <code class="bg-gray-700 px-1 rounded">idf.py build</code> 编译项目</li>
                </ul>
                <div class="mt-3 pt-3 border-t border-blue-700">
                    <button id="export-as-text-btn" class="text-xs bg-gray-700 hover:bg-gray-600 text-white py-1 px-3 rounded">
                        <i class="fas fa-file-alt mr-1"></i>导出为文本（备选方案）
                    </button>
                </div>
            </div>
        </div>
    `;
    
    // 插入到下载按钮区域
    const downloadSection = document.getElementById('download-zip').closest('.flex');
    if (downloadSection) {
        downloadSection.parentNode.insertBefore(instructionDiv, downloadSection.nextSibling);
        
        // 添加导出为文本按钮事件
        setTimeout(() => {
            const exportTextBtn = document.getElementById('export-as-text-btn');
            if (exportTextBtn) {
                exportTextBtn.addEventListener('click', exportProjectAsTextAlternative);
            }
        }, 100);
        
        // 15秒后自动移除说明
        setTimeout(() => {
            if (instructionDiv.parentNode) {
                instructionDiv.parentNode.removeChild(instructionDiv);
            }
        }, 15000);
    }
}

// 导出为文本的备选方案
function exportProjectAsTextAlternative() {
    const projectText = exportProjectAsText();
    
    // 创建可下载的文本文件
    const blob = new Blob([projectText], { type: 'text/plain;charset=utf-8' });
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
    const fileName = `${appState.projectName}_${timestamp}_source.txt`;
    saveAs(blob, fileName);
    
    logToMonitor(`项目源码已导出为文本文件: ${fileName}`, 'success');
    
    // 显示使用说明
    showTextExportInstructions();
}

// 显示文本导出说明
function showTextExportInstructions() {
    const instructionDiv = document.createElement('div');
    instructionDiv.className = 'mt-4 p-4 bg-green-900 rounded-lg text-sm';
    instructionDiv.innerHTML = `
        <div class="flex items-start">
            <i class="fas fa-check-circle text-green-400 mt-1 mr-2"></i>
            <div>
                <p class="font-semibold mb-2">文本导出成功：</p>
                <ul class="list-disc pl-5 space-y-1">
                    <li>文本文件包含所有项目源码，不会被安全软件阻止</li>
                    <li>可按以下步骤重建项目：</li>
                    <li class="ml-5">1. 创建新目录并进入</li>
                    <li class="ml-5">2. 按文件结构创建对应文件</li>
                    <li class="ml-5">3. 将文本中对应内容复制到各文件</li>
                    <li class="ml-5">4. 使用idf.py build编译项目</li>
                </ul>
            </div>
        </div>
    `;
    
    const exportBtn = document.getElementById('export-as-text-btn');
    if (exportBtn) {
        const parentDiv = exportBtn.closest('.mt-4');
        if (parentDiv) {
            parentDiv.parentNode.insertBefore(instructionDiv, parentDiv.nextSibling);
        }
    }
}

// 导出项目结构为文本
function exportProjectStructure() {
    if (Object.keys(appState.projectFiles).length === 0) {
        alert('请先生成代码！');
        logToMonitor('导出失败：请先生成代码', 'error');
        return;
    }

    let structureText = `# ESP32 项目结构\n`;
    structureText += `项目名称: ${appState.projectName}\n`;
    structureText += `芯片型号: ${appState.chipModel}\n`;
    structureText += `生成时间: ${new Date().toLocaleString('zh-CN')}\n\n`;
    
    structureText += `${appState.projectName}/\n`;
    structureText += `├── CMakeLists.txt\n`;
    structureText += `├── sdkconfig\n`;
    
    if (appState.otaEnabled) {
        structureText += `├── partitions.csv\n`;
    }
    
    structureText += `├── main/\n`;
    structureText += `│   └── main.c\n`;
    
    if (hasSpecialComponents()) {
        structureText += `└── components/\n`;
        structureText += `    └── ...\n`;
    }
    
    structureText += `\n# 使用说明\n`;
    structureText += `1. 创建项目目录\n`;
    structureText += `2. 按照以上结构创建文件和文件夹\n`;
    structureText += `3. 将生成的代码复制到对应文件中\n`;
    structureText += `4. 在ESP-IDF环境中使用 idf.py build 编译项目\n`;

    // 复制到剪贴板
    navigator.clipboard.writeText(structureText)
        .then(() => {
            logToMonitor('项目结构和使用说明已复制到剪贴板', 'success');
            showExportInstructions();
        })
        .catch(err => {
            logToMonitor('复制失败：' + err, 'error');
        });
}

// 显示导出说明
function showExportInstructions() {
    // 检查是否已存在说明
    const existingInstructions = document.querySelector('.export-instructions');
    if (existingInstructions) {
        existingInstructions.remove();
    }
    
    // 创建说明元素
    const instructionDiv = document.createElement('div');
    instructionDiv.className = 'mt-4 p-4 bg-green-900 rounded-lg text-sm export-instructions';
    instructionDiv.innerHTML = `
        <div class="flex items-start">
            <i class="fas fa-check-circle text-green-400 mt-1 mr-2"></i>
            <div>
                <p class="font-semibold mb-2">导出成功：</p>
                <ul class="list-disc pl-5 space-y-1">
                    <li>项目结构和使用说明已复制到剪贴板</li>
                    <li>可粘贴到文本编辑器中保存为 README.md</li>
                    <li>按照说明创建项目文件结构</li>
                </ul>
            </div>
        </div>
    `;
    
    // 插入到导出按钮区域
    const exportSection = document.getElementById('export-text').closest('.flex');
    if (exportSection) {
        exportSection.parentNode.insertBefore(instructionDiv, exportSection.nextSibling);
        
        // 10秒后自动移除说明
        setTimeout(() => {
            if (instructionDiv.parentNode) {
                instructionDiv.parentNode.removeChild(instructionDiv);
            }
        }, 10000);
    }
}

// 连接到设备
async function connectToDevice() {
    if (!('serial' in navigator)) {
        alert('您的浏览器不支持Web Serial API，请使用最新版Chrome浏览器');
        logToMonitor('浏览器不支持Web Serial API', 'error');
        return;
    }

    try {
        // 请求用户选择串口
        appState.serialPort = await navigator.serial.requestPort();

        // 打开串口
        await appState.serialPort.open({ baudRate: 115200 });

        // 更新UI
        const statusIndicator = elements.connectionStatus.querySelector('.status-indicator');
        statusIndicator.classList.remove('status-disconnected');
        statusIndicator.classList.add('status-connected');
        elements.connectionStatus.innerHTML = '<span class="status-indicator status-connected"></span>已连接设备';
        elements.connectDeviceBtn.innerHTML = '<i class="fas fa-unlink mr-2"></i>断开连接';
        elements.connectDeviceBtn.classList.remove('bg-gradient-to-r', 'from-blue-500', 'to-indigo-600');
        elements.connectDeviceBtn.classList.add('bg-gradient-to-r', 'from-red-500', 'to-orange-600');

        // 启用烧录按钮
        elements.flashFirmwareBtn.disabled = false;
        
        // 更改点击事件处理函数
        elements.connectDeviceBtn.removeEventListener('click', connectToDevice);
        elements.connectDeviceBtn.addEventListener('click', disconnectFromDevice);

        logToMonitor('设备已连接', 'success');
    } catch (error) {
        console.error('连接设备时出错:', error);
        logToMonitor('连接设备失败: ' + error.message, 'error');
        alert('连接设备失败: ' + error.message);
    }
}

// 断开设备连接
async function disconnectFromDevice() {
    if (appState.serialPort) {
        try {
            await appState.serialPort.close();
            appState.serialPort = null;

            // 更新UI
            const statusIndicator = elements.connectionStatus.querySelector('.status-indicator');
            statusIndicator.classList.remove('status-connected');
            statusIndicator.classList.add('status-disconnected');
            elements.connectionStatus.innerHTML = '<span class="status-indicator status-disconnected"></span>未连接设备';
            elements.connectDeviceBtn.innerHTML = '<i class="fas fa-link mr-2"></i>连接设备';
            elements.connectDeviceBtn.classList.remove('bg-gradient-to-r', 'from-red-500', 'to-orange-600');
            elements.connectDeviceBtn.classList.add('bg-gradient-to-r', 'from-blue-500', 'to-indigo-600');

            // 禁用烧录按钮
            elements.flashFirmwareBtn.disabled = true;
            
            // 更改点击事件处理函数
            elements.connectDeviceBtn.removeEventListener('click', disconnectFromDevice);
            elements.connectDeviceBtn.addEventListener('click', connectToDevice);

            logToMonitor('设备已断开连接', 'info');
        } catch (error) {
            console.error('断开设备连接时出错:', error);
            logToMonitor('断开连接时出错: ' + error.message, 'error');
        }
    }
}

// 处理固件文件选择
function handleFirmwareSelection(event) {
    const file = event.target.files[0];
    if (file) {
        logToMonitor(`已选择固件文件: ${file.name}`, 'info');
        elements.flashFirmwareBtn.disabled = false;
    }
}

// 烧录固件
async function flashFirmware() {
    if (!appState.serialPort) {
        alert('请先连接设备');
        logToMonitor('烧录失败：请先连接设备', 'error');
        return;
    }

    const file = elements.firmwareFileInput.files[0];
    if (!file) {
        alert('请选择固件文件');
        logToMonitor('烧录失败：请选择固件文件', 'error');
        return;
    }

    // 模拟烧录过程
    simulateFlashing();
}

// 模拟烧录过程
function simulateFlashing() {
    logToMonitor('开始烧录固件...', 'info');
    let progress = 0;
    elements.flashProgress.style.width = '0%';
    elements.progressPercent.textContent = '0%';

    const interval = setInterval(() => {
        progress += Math.random() * 10;
        if (progress >= 100) {
            progress = 100;
            clearInterval(interval);
        }

        elements.flashProgress.style.width = progress + '%';
        elements.progressPercent.textContent = Math.round(progress) + '%';
    }, 200);

    setTimeout(() => {
        if (progress >= 100) {
            logToMonitor('固件烧录成功！', 'success');
            alert('固件烧录成功！');
        }
    }, 2500);
}

// 发送串口命令
function sendSerialCommand() {
    const command = elements.serialCommand.value.trim();
    if (!command) return;
    
    logToMonitor(`> ${command}`, 'info');
    elements.serialCommand.value = '';
}

// 记录到串口监视器
function logToMonitor(message, type = 'info') {
    const timestamp = new Date().toLocaleTimeString();
    const messageElement = document.createElement('p');
    
    // 根据消息类型设置样式
    switch(type) {
        case 'error':
            messageElement.className = 'serial-error';
            break;
        case 'success':
            messageElement.className = 'serial-success';
            break;
        case 'info':
            messageElement.className = 'serial-info';
            break;
        default:
            messageElement.className = 'serial-message';
    }
    
    messageElement.textContent = `[${timestamp}] ${message}`;
    elements.serialMonitor.appendChild(messageElement);
    
    // 滚动到底部
    elements.serialMonitor.scrollTop = elements.serialMonitor.scrollHeight;
}

// 保存配置到localStorage
function saveConfiguration() {
    const config = {
        chipModel: appState.chipModel,
        projectName: appState.projectName,
        wifiEnabled: appState.wifiEnabled,
        bluetoothEnabled: appState.bluetoothEnabled,
        httpServerEnabled: appState.httpServerEnabled,
        otaEnabled: appState.otaEnabled,
        pinConfigurations: appState.pinConfigurations
    };

    localStorage.setItem('esp32_config', JSON.stringify(config));
}

// 加载配置
function loadConfiguration() {
    const savedConfig = localStorage.getItem('esp32_config');
    if (savedConfig) {
        try {
            const config = JSON.parse(savedConfig);
            appState.chipModel = config.chipModel || appState.chipModel;
            appState.projectName = config.projectName || appState.projectName;
            appState.wifiEnabled = config.wifiEnabled || appState.wifiEnabled;
            appState.bluetoothEnabled = config.bluetoothEnabled || appState.bluetoothEnabled;
            appState.httpServerEnabled = config.httpServerEnabled || appState.httpServerEnabled;
            appState.otaEnabled = config.otaEnabled || appState.otaEnabled;
            appState.pinConfigurations = config.pinConfigurations || appState.pinConfigurations;

            // 更新UI
            elements.chipSelector.value = appState.chipModel;
            elements.projectName.value = appState.projectName;
            elements.wifiEnable.checked = appState.wifiEnabled;
            elements.bluetoothEnable.checked = appState.bluetoothEnabled;
            elements.httpServerEnable.checked = appState.httpServerEnabled;
            elements.otaEnable.checked = appState.otaEnabled;

            logToMonitor('配置已加载', 'info');
        } catch (e) {
            console.error('加载配置时出错:', e);
            logToMonitor('加载配置时出错', 'error');
        }
    }
}

// 工具函数：转义HTML
function escapeHtml(unsafe) {
    return unsafe
         .replace(/&/g, "&amp;")
         .replace(/</g, "&lt;")
         .replace(/>/g, "&gt;")
         .replace(/"/g, "&quot;")
         .replace(/'/g, "&#039;");
}

// 页面加载完成后初始化应用
document.addEventListener('DOMContentLoaded', initApp);